package com.gzh.teaching.service.impl;

import com.gzh.core.dao.mapper.*;
import com.gzh.core.dao.po.*;
import com.gzh.core.util.CosUtils;
import com.gzh.core.util.NumericHelper;
import com.gzh.core.util.StringUtils;
import com.gzh.core.util.constant.ErrorCode;
import com.gzh.core.util.exception.BusinessException;
import com.gzh.teaching.dao.mapper.StudentMapper;
import com.gzh.teaching.model.vo.CheckInParam;
import com.gzh.teaching.model.vo.GetJobOut;
import com.gzh.teaching.service.StudentService;
import com.gzh.teaching.service.dto.*;
import com.xxl.job.core.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Condition;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class StudentServiceImpl implements StudentService {
  @Autowired
  private CourseMapper courseMapper;
  @Autowired
  private ChooseMapper chooseMapper;
  @Autowired
  private UserMapper userMapper;
  @Autowired
  private WorkMapper workMapper;
  @Autowired
  private FileMapper fileMapper;
  @Autowired
  private AnswerMapper answerMapper;
  @Autowired
  private QuestionMapper questionMapper;
  @Autowired
  private StudentMapper studentMapper;
  @Autowired
  private CompleteMapper completeMapper;
  @Autowired
  private CheckMapper checkMapper;
  @Autowired
  private CheckInMapper checkInMapper;
  @Override
  public void pickCourse(PickCourseIn in) {
    CourseEntity courseEntityQuery = new CourseEntity();
    courseEntityQuery.setCourseId(in.getCourseId());
    CourseEntity courseEntity = courseMapper.selectOne(courseEntityQuery);
    if (courseEntity.getStatus() != 0){
      throw new BusinessException(ErrorCode.STUDENT_121);
    }
    Condition chooseCondition = new Condition(ChooseEntity.class);
    chooseCondition.createCriteria().andEqualTo("userId",in.getUserId())
      .andEqualTo("courseId",in.getCourseId());
    List<ChooseEntity> chooseEntityList = chooseMapper.selectByCondition(chooseCondition);
    if (!CollectionUtils.isEmpty(chooseEntityList)){
      throw new BusinessException(ErrorCode.STUDENT_122);
    }
    ChooseEntity chooseEntity = new ChooseEntity();
    chooseEntity.setUserId(in.getUserId());
    chooseEntity.setCourseId(in.getCourseId());
    chooseEntity.setJoinDate(NumericHelper.toInteger(StringUtils.formatDate()));
    chooseEntity.setJoinTime(NumericHelper.toInteger(StringUtils.formatTime()));
    chooseMapper.insertSelective(chooseEntity);
  }

  @Override
  public List<PickCourseOut> getPickCourse(PickCourseIn in) {
    List<PickCourseOut> list = new ArrayList<>();
    Integer userId = in.getUserId();
    Condition chooseCondition = new Condition(ChooseEntity.class);
    Example.Criteria criteria = chooseCondition.createCriteria();
    criteria.andEqualTo("userId",userId);
    if (in.getKey() != null){
      criteria.andEqualTo("courseId",in.getKey());
    }
    List<ChooseEntity> chooseEntityList = chooseMapper.selectByCondition(chooseCondition);
    if (!CollectionUtils.isEmpty(chooseEntityList)){
      List<Integer> courseIdList = chooseEntityList.stream().map(t -> t.getCourseId()).collect(Collectors.toList());
      Condition courseCondition = new Condition(CourseEntity.class);
      courseCondition.createCriteria().andIn("courseId",courseIdList)
        .andIn("status", Arrays.asList(0,2));
      List<CourseEntity> courseEntityList = courseMapper.selectByCondition(courseCondition);
      if (!CollectionUtils.isEmpty(courseEntityList)){
        List<Integer> teacherIdList = courseEntityList.stream().map(t -> t.getTeacherId()).collect(Collectors.toList());
        Condition userCondition = new Condition(UserEntity.class);
        userCondition.createCriteria().andIn("userId",teacherIdList);
        List<UserEntity> userEntityList = userMapper.selectByCondition(userCondition);
        for (CourseEntity courseEntity : courseEntityList) {
          List<UserEntity> userEntities = userEntityList.stream().filter(t -> t.getUserId().equals(courseEntity.getTeacherId())).collect(Collectors.toList());
          PickCourseOut out = new PickCourseOut();
          out.setCourseId(StringUtils.toString(courseEntity.getCourseId()));
          out.setCourseName(courseEntity.getCourseName());
          out.setImgPath(courseEntity.getImgPath());
          out.setUserName(userEntities.get(0).getFullName());
          out.setCourseType(StringUtils.toString(courseEntity.getCourseType()));
          out.setStatus(StringUtils.toString(courseEntity.getStatus()));
          out.setCreateDate(StringUtils.toString(courseEntity.getCreateDate()));
          out.setCreateTime(StringUtils.toString(courseEntity.getCreateTime()));
          out.setCredit(StringUtils.toString(courseEntity.getCredit()));
          out.setIntroduce(courseEntity.getIntroduce());
          list.add(out);
        }
      }
    }
    return list;
  }

  @Override
  public List<GetJobOut> getNormalWork(GetJobIn in) {
    List<GetJobOut> list = new ArrayList<>();
    Integer courseId = in.getCourseId();
    Condition workCondition = new Condition(WorkEntity.class);
    workCondition.createCriteria().andEqualTo("courseId", courseId)
            .andEqualTo("isPublish",1);
    workCondition.setOrderByClause("create_date desc,create_time desc");
    List<WorkEntity> workEntityList = workMapper.selectByCondition(workCondition);
    if (!CollectionUtils.isEmpty(workEntityList)) {
      //查看是否完成
      List<Integer> workIdList = workEntityList.stream().map(t -> t.getWorkId()).collect(Collectors.toList());
      Condition completeCondition = new Condition(CompleteEntity.class);
      completeCondition.createCriteria().andIn("workId",workIdList)
              .andEqualTo("userId",in.getUserId());
      List<CompleteEntity> completeEntityList = completeMapper.selectByCondition(completeCondition);
      //查询文件路径
      List<Integer> fileIdList = workEntityList.stream().filter(t -> t.getWorkType().equals(1)).map(t -> t.getFileId()).collect(Collectors.toList());
      List<FileEntity> fileEntityList = new ArrayList<>();
      if (!CollectionUtils.isEmpty(fileIdList)){
        Condition fileCondition = new Condition(FileEntity.class);
        fileCondition.createCriteria().andIn("fileId", fileIdList);
        fileEntityList = fileMapper.selectByCondition(fileCondition);
      }
      for (WorkEntity workEntity : workEntityList) {
        GetJobOut getJobOut = new GetJobOut(workEntity);
        List<CompleteEntity> entityList = completeEntityList.stream().filter(t -> workEntity.getWorkId().equals(t.getWorkId())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(entityList)){
          getJobOut.setCompleteType(StringUtils.toString(entityList.get(0).getCompleteType()));
          getJobOut.setScore(StringUtils.toString(entityList.get(0).getScore()));
        }
        if (workEntity.getWorkType().equals(1)) {
          List<FileEntity> entities = fileEntityList.stream().filter(t -> t.getFileId().equals(workEntity.getFileId())).collect(Collectors.toList());
          if (!CollectionUtils.isEmpty(entities)) {
            String objectUrl = CosUtils.getImg(entities.get(0).getBucketName(), entities.get(0).getPath());
            getJobOut.setFilePath(objectUrl);
            getJobOut.setFileName(entities.get(0).getFileName());
          }
        }
        list.add(getJobOut);
      }
    }
    return list;
  }

  @Override
  public GetWorkOut getWork(GetJobIn in) {
    GetWorkOut out = new GetWorkOut();
    Integer workId = in.getWorkId();
    //工作表
    WorkEntity workEntityQuery = new WorkEntity();
    workEntityQuery.setWorkId(workId);
    WorkEntity workEntity = workMapper.selectOne(workEntityQuery);
    out.setWorkName(workEntity.getWorkName());
    //问题
    Condition questionCondition = new Condition(QuestionEntity.class);
    questionCondition.createCriteria().andEqualTo("workId",workId);
    List<QuestionEntity> questionEntityList = questionMapper.selectByCondition(questionCondition);
    List<GetWorkInfo> list = questionEntityList.stream().map(t -> new GetWorkInfo(t)).collect(Collectors.toList());
    //答案
    Condition answerCondition = new Condition(AnswerEntity.class);
    answerCondition.createCriteria().andEqualTo("workId",workId)
              .andEqualTo("userId",in.getUserId());
    List<AnswerEntity> answerEntityList = answerMapper.selectByCondition(answerCondition);

    if (!CollectionUtils.isEmpty(answerEntityList)){
      //有答案了
      Map<Integer, List<AnswerEntity>> listMap = answerEntityList.stream().collect(Collectors.groupingBy(t -> t.getQuestionId()));
      for (GetWorkInfo getWorkInfo : list) {
        Integer questionId = getWorkInfo.getQuestionId();
        List<AnswerEntity> answerEntities = listMap.get(questionId);
        getWorkInfo.setUserAnswer(answerEntities.get(0).getAnswer());
        getWorkInfo.setAnswerId(StringUtils.toString(answerEntities.get(0).getAnswerId()));
        getWorkInfo.setResult(StringUtils.toString(answerEntities.get(0).getResult()));
      }
    }
    Condition completeCondition = new Condition(CompleteEntity.class);
    completeCondition.createCriteria().andEqualTo("workId",workId)
      .andEqualTo("userId",in.getUserId());
    List<CompleteEntity> completeEntityList = completeMapper.selectByCondition(completeCondition);
    if (!CollectionUtils.isEmpty(completeEntityList)){
      out.setCompleteType(StringUtils.toString(completeEntityList.get(0).getCompleteType()));
      out.setCompleteDate(StringUtils.toString(completeEntityList.get(0).getCompleteDate()));
      out.setCompleteTime(StringUtils.toString(completeEntityList.get(0).getCompleteTime()));
      out.setScore(StringUtils.toString(completeEntityList.get(0).getScore()));
      out.setComment(completeEntityList.get(0).getComment());
      out.setIsCorrect(StringUtils.toString(completeEntityList.get(0).getIsCorrect()));
    }
    out.setList(list);
    return out;
  }

  @Override
  public GetReportOut getReport(GetJobIn in) {
    GetReportOut out = null;
    Integer workId = in.getWorkId();
    //工作表
    WorkEntity workEntityQuery = new WorkEntity();
    workEntityQuery.setWorkId(workId);
    WorkEntity workEntity = workMapper.selectOne(workEntityQuery);
    out = new GetReportOut(workEntity);
    //答案
    Condition answerCondition = new Condition(AnswerEntity.class);
    answerCondition.createCriteria().andEqualTo("workId",workId)
      .andEqualTo("userId",in.getUserId());
    List<AnswerEntity> answerEntityList = answerMapper.selectByCondition(answerCondition);
    List<Integer> fileIdList = new ArrayList<>();
    Integer fileId = workEntity.getFileId();
    fileIdList.add(fileId);
    if (!CollectionUtils.isEmpty(answerEntityList)){
      //有答案了
      Integer answerFileId = NumericHelper.toInteger(answerEntityList.get(0).getAnswer());
      fileIdList.add(answerFileId);
      out.setAnswerId(StringUtils.toString(answerEntityList.get(0).getAnswerId()));
    }
    Condition fileCondition = new Condition(FileEntity.class);
    fileCondition.createCriteria().andIn("fileId",fileIdList);
    List<FileEntity> fileEntityList = fileMapper.selectByCondition(fileCondition);
    for (FileEntity fileEntity : fileEntityList) {
      if (fileEntity.getFileId().equals(fileId)){
        out.setFilePath(CosUtils.getImg(fileEntity.getBucketName(),fileEntity.getPath()));
        out.setFileName(fileEntity.getFileName());
      }else {
        out.setAnswerFilePath(CosUtils.getImg(fileEntity.getBucketName(),fileEntity.getPath()));
        out.setAnswerFileName(fileEntity.getFileName());
      }
    }
    Condition completeCondition = new Condition(CompleteEntity.class);
    completeCondition.createCriteria().andEqualTo("workId",workId)
      .andEqualTo("userId",in.getUserId());
    List<CompleteEntity> completeEntityList = completeMapper.selectByCondition(completeCondition);
    if (!CollectionUtils.isEmpty(completeEntityList)){
      out.setCompleteType(StringUtils.toString(completeEntityList.get(0).getCompleteType()));
      out.setCompleteDate(StringUtils.toString(completeEntityList.get(0).getCompleteDate()));
      out.setCompleteTime(StringUtils.toString(completeEntityList.get(0).getCompleteTime()));
      out.setScore(StringUtils.toString(completeEntityList.get(0).getScore()));
      out.setComment(completeEntityList.get(0).getComment());
      out.setIsCorrect(StringUtils.toString(completeEntityList.get(0).getIsCorrect()));
    }
    return out;
  }

  @Override
  @Transactional
  public void saveReport(SaveReportIn in) {
    Integer workId = in.getWorkId();
    checkWork(workId);
    Integer userId = in.getUserId();
    Integer type = in.getType();
    Integer answerId = in.getAnswerId();
    //答案表
    if (StringUtils.isNotEmpty(StringUtils.toString(answerId))){
      Condition answerCondition = new Condition(AnswerEntity.class);
      answerCondition.createCriteria().andEqualTo("answerId",answerId);
      answerMapper.deleteByCondition(answerCondition);
    }
    AnswerEntity answerEntity = new AnswerEntity();
    answerEntity.setAnswer(StringUtils.toString(in.getFileId()));
    answerEntity.setUserId(userId);
    answerEntity.setWorkId(workId);
    answerMapper.insertSelective(answerEntity);
    //删除完成表
    Condition completeCondition = new Condition(CompleteEntity.class);
    completeCondition.createCriteria().andEqualTo("workId",workId)
            .andEqualTo("userId",userId);
    completeMapper.deleteByCondition(completeCondition);
    //新增
    CompleteEntity completeEntity = new CompleteEntity();
    completeEntity.setCompleteType(type);
    completeEntity.setUserId(userId);
    completeEntity.setWorkId(workId);
    completeEntity.setCompleteDate(NumericHelper.toInteger(StringUtils.formatDate()));
    completeEntity.setCompleteTime(NumericHelper.toInteger(StringUtils.formatTime()));
    completeMapper.insertSelective(completeEntity);
  }

  @Override
  @Transactional
  public void saveWorkAnswer(SaveWorkAnswerIn in) {
    Integer workId = in.getWorkId();
    checkWork(workId);
    Integer userId = in.getUserId();
    Integer type = in.getType();
    List<GetWorkInfo> list = in.getList();
    List<Integer> answerIdList = list.stream().map(t -> NumericHelper.toInteger(t.getAnswerId())).collect(Collectors.toList());
    //删原来的答案
    Condition answerCondition = new Condition(AnswerEntity.class);
    answerCondition.createCriteria().andIn("answerId",answerIdList);
    answerMapper.deleteByCondition(answerCondition);
    List<AnswerEntity> answerEntityList = new ArrayList<>();
    for (GetWorkInfo getWorkInfo : list) {
      Integer result = 0;
      String answer = getWorkInfo.getAnswer();
      String userAnswer = getWorkInfo.getUserAnswer();
      String questionType = getWorkInfo.getQuestionType();
      if (questionType.equals("1") || questionType.equals("4") ||questionType.equals("3")){
        if (answer.equals(userAnswer)){
          result = 1;
        }
      }
      if (questionType.equals("2")){
        result = 1;
        List<String> answerTwo = Arrays.asList(answer.split(","));
        List<String> userAnswerTwo = Arrays.asList(userAnswer.split(","));
        if (answerTwo.size() == userAnswerTwo.size()){
          for (String answerIndex : answerTwo) {
            if (!userAnswerTwo.contains(answerIndex)){
              result = 0;
              break;
            }
          }
        }else {
          result = 0;
        }
      }

      AnswerEntity answerEntity = new AnswerEntity();
      answerEntity.setAnswer(userAnswer);
      answerEntity.setWorkId(workId);
      answerEntity.setResult(result);
      answerEntity.setQuestionId(getWorkInfo.getQuestionId());
      answerEntity.setUserId(userId);
      answerEntityList.add(answerEntity);
    }
    answerMapper.insertList(answerEntityList);
    //删除完成表
    Condition completeCondition = new Condition(CompleteEntity.class);
    completeCondition.createCriteria().andEqualTo("workId",workId)
            .andEqualTo("userId",userId);
    completeMapper.deleteByCondition(completeCondition);
    //新增
    CompleteEntity completeEntity = new CompleteEntity();
    completeEntity.setCompleteType(type);
    completeEntity.setUserId(userId);
    completeEntity.setWorkId(workId);
    completeEntity.setCompleteDate(NumericHelper.toInteger(StringUtils.formatDate()));
    completeEntity.setCompleteTime(NumericHelper.toInteger(StringUtils.formatTime()));
    completeMapper.insertSelective(completeEntity);
  }

  @Override
  public void checkIn(CheckInParam param) {
    String code = param.getCode();
    String checkId = param.getCheckId();
    String info = param.getInfo();
    if (StringUtils.isEmpty(checkId) || StringUtils.isEmpty(info) || StringUtils.isEmpty(code)){
      throw new BusinessException(ErrorCode.CHECK_100);
    }
    CheckEntity checkEntityQuery = new CheckEntity();
    checkEntityQuery.setCheckId(NumericHelper.toInteger(checkId));
    CheckEntity checkEntity = checkMapper.selectOne(checkEntityQuery);
    if (checkEntity == null){
      throw new BusinessException(ErrorCode.CHECK_101);
    }
    if (!checkEntity.getCheckCode().equals(code)){
      throw new BusinessException(ErrorCode.CHECK_104);
    }
    //15分钟后不能
    Integer checkTime = checkEntity.getCheckTime();
    Integer time = NumericHelper.toInteger(StringUtils.formatTime());
    Integer expiredTime = StringUtils.addTime(checkTime, 15);
    if (expiredTime < time){
      throw new BusinessException(ErrorCode.CHECK_106);
    }
    Condition userCondition = new Condition(UserEntity.class);
    userCondition.createCriteria().orEqualTo("tel",info)
            .orEqualTo("mail",info)
            .orEqualTo("stuId",info);
    List<UserEntity> userEntityList = userMapper.selectByCondition(userCondition);
    if (CollectionUtils.isEmpty(userEntityList)){
      throw new BusinessException(ErrorCode.CHECK_103);
    }
    List<Integer> userIds = userEntityList.stream().map(t -> t.getUserId()).distinct().collect(Collectors.toList());
    Integer userId = userIds.get(0);
    Condition checkInCondition = new Condition(CheckInEntity.class);
    checkInCondition.createCriteria().andEqualTo("checkId",NumericHelper.toInteger(checkId));
    List<CheckInEntity> checkInEntities = checkInMapper.selectByCondition(checkInCondition);
    List<Integer> userIdList = checkInEntities.stream().map(t -> t.getUserId()).distinct().collect(Collectors.toList());
    if (!CollectionUtils.isEmpty(userIdList) && userIdList.contains(userId)){
      throw new BusinessException(ErrorCode.CHECK_102);
    }
    Integer courseId = checkEntity.getCourseId();
    Condition chooseCondition = new Condition(ChooseEntity.class);
    chooseCondition.createCriteria().andEqualTo("courseId",courseId);
    List<ChooseEntity> chooseEntityList = chooseMapper.selectByCondition(chooseCondition);
    List<Integer> userInCourseList = chooseEntityList.stream().map(t -> t.getUserId()).distinct().collect(Collectors.toList());
    if (!userInCourseList.contains(userId)){
      throw new BusinessException(ErrorCode.CHECK_105);
    }
    CheckInEntity checkInEntity = new CheckInEntity();
    checkInEntity.setCheckId(NumericHelper.toInteger(checkId));
    checkInEntity.setCheckDate(NumericHelper.toInteger(StringUtils.formatDate()));
    checkInEntity.setCheckTime(NumericHelper.toInteger(StringUtils.formatTime()));
    checkInEntity.setUserId(userId);
    checkInMapper.insertSelective(checkInEntity);
  }

  /**
   * 看作业是否结束
   * @param workId
   */
  public void checkWork(Integer workId){
    Integer date = NumericHelper.toInteger(StringUtils.formatDate());
    Integer time = NumericHelper.toInteger(StringUtils.formatTime());
    WorkEntity workEntityQuery = new WorkEntity();
    workEntityQuery.setWorkId(workId);
    WorkEntity workEntity = workMapper.selectOne(workEntityQuery);
    Integer isEnd = workEntity.getIsEnd();
    Integer endDate = workEntity.getEndDate();
    Integer endTime = workEntity.getEndTime();
    if (isEnd.equals(1) || date > endDate || (date.equals(endDate) && time > endTime)){
      throw new BusinessException(ErrorCode.STUDENT_123);
    }
  }
}
